package com.iplatform.iplatformuser.privilege.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.iplatform.commons.utils.CommResponse;
import com.iplatform.iplatformuser.privilege.dao.SysdataMapper;
import com.iplatform.iplatformuser.privilege.service.inter.ISysDataService;
import com.iplatform.iplatformuser.privilege.util.RedisUtils;
import com.iplatform.module.sys.SysDataBean;
import com.iplatform.module.sys.dto.SysDataTypeDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.KeyBoundCursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.xml.crypto.Data;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Title: SysDataServiceImpl
 * Description:
 *
 * @author RayLLi
 * @date 2018年8月28日
 */
@Slf4j
@Service
public class SysDataServiceImpl implements ISysDataService {

    @Autowired
    public SysdataMapper sysdataMapper;
    @Autowired
    public RedisTemplate redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public List<HashMap<String, String>> loadData() {
        return sysdataMapper.loadData();
    }

    @Override
    public List<HashMap<String, String>> querySysData(Map<String, String> formMap) {
        return sysdataMapper.querySysData(formMap);
    }

    @Override
    @Transactional
    public int insertSysData(SysDataBean sysDataBean) {
        operationOrd(sysDataBean);
        return sysdataMapper.insertSysData(sysDataBean);
    }

    /**
     * 自动排序
     * author ld
     * @param sysDataBean
     */
    @Transactional
    public void operationOrd(SysDataBean sysDataBean){
        if (sysDataBean.getTypeOrdNo() != null){
            //获取类型的排序码集合
            List<SysDataTypeDto> sysDataTypeDtos = sysdataMapper.findOrdNo(sysDataBean.getTypeCode(),1,sysDataBean.getDataId());
            List<BigDecimal> typeOrdNos = new ArrayList<>();
            //遍历
            for (SysDataTypeDto sysDataTypeDto : sysDataTypeDtos){
                typeOrdNos.add(sysDataTypeDto.getTypeOrdNo());
                //判断新增的类型排序码是否在数据库中存在
            }
            if (typeOrdNos.contains(sysDataBean.getTypeOrdNo())){
                //获取应该修改排序码的数据类型id
                List<String> typeIds = sysdataMapper.findByOrdNo(sysDataBean.getTypeCode(),null,sysDataBean.getTypeOrdNo(),sysDataBean.getDataId());
                //将这些数据类型的排序码+1
                sysdataMapper.typeOrdNoAddOne(typeIds);
            }
        }

        if (sysDataBean.getOrdNo() != null){
            //数据的排序码
            List<SysDataTypeDto> sysDataTypeDtoList = sysdataMapper.findOrdNo(sysDataBean.getTypeCode(),0,sysDataBean.getDataId());
            List<BigDecimal> ordNos = new ArrayList<>();
            for (SysDataTypeDto sysDataDto : sysDataTypeDtoList){
                ordNos.add(sysDataDto.getOrdNo());
            }
            if (ordNos.contains(sysDataBean.getOrdNo())){
                List<String> ids = sysdataMapper.findByOrdNo(sysDataBean.getTypeCode(),sysDataBean.getOrdNo(),null,sysDataBean.getDataId());
                sysdataMapper.ordNoAddOne(ids);
            }
        }

    }

    @Override
    @Transactional
    public int updateSysData(Map<String, String> formMap) {
        return sysdataMapper.updateSysData(formMap);
    }

    @Override
    @Transactional
    public void deleteSysData(String id) {
        sysdataMapper.deleteSysData(id);
    }

    @Override
    @Transactional
    public void batchDeleteSysData(List<String> ids) {
        sysdataMapper.batchDeleteSysData(ids);
    }

    @Override
    @Transactional
    public void setReadOnlyStatus(String id) {
        sysdataMapper.setReadOnlyStatus(id);
    }

    @Override
    public List<HashMap<String, String>> queryCodeAndName() {
        return sysdataMapper.queryCodeAndName();
    }

    @Override
    public List<String> querySysDataByType(Map<String, String> map) {
        return sysdataMapper.querySysDataByType(map);
    }

    @Override
    public List<HashMap<String, String>> loadSycDate() {
        return sysdataMapper.loadSycDate();
    }

    @Override
    public List<SysDataTypeDto> querySysDataByTypeCode(String typeCode, String code, String codeName,String dataType) {
        return sysdataMapper.querySysDataByTypeCode(typeCode, code, codeName,dataType);
    }

    @Override
    public void setDataType(String id, String dataType) {
        sysdataMapper.setDataType(id, dataType);
    }

    @Override
    public String findDataTypeByDataId(String id) {
        return sysdataMapper.findDataTypeByDataId(id);
    }

    @Override
    public List<SysDataTypeDto> findTypeCodeAndTypeName(String typeName) {
        return sysdataMapper.findTypeCodeAndTypeName(typeName);
    }

    @Override
    public SysDataBean isCodeExist(String typeCode, String code, String id) {
        return sysdataMapper.isCodeExist(typeCode, code, id);
    }

    @Override
    @Transactional
    public CommResponse updateType(SysDataBean sysDataBean) {
        operationOrd(sysDataBean);
        SysDataTypeDto newSysDataTypeDto= sysdataMapper.findTypeById(sysDataBean.getDataId());
        List<String> ids = sysdataMapper.findIdByType(newSysDataTypeDto.getTypeName());
        if (sysdataMapper.updateType(sysDataBean,ids) < 0){
            return new CommResponse("修改类型失败",false);
        }
        return new CommResponse("修改类型成功",true);
    }

    @Override
    @Transactional
    public CommResponse updateData(SysDataBean sysDataBean) {
        operationOrd(sysDataBean);
        return new CommResponse("修改数据排序码成功",true);
    }

    @Override
    public void batchDeleteType(List<String> ids) {
        for (String id : ids){
            SysDataTypeDto newSysDataTypeDto= sysdataMapper.findTypeById(id);
            List<String> typeIds = sysdataMapper.findIdByType(newSysDataTypeDto.getTypeName());
            sysdataMapper.batchDeleteType(typeIds);
        }
    }

    @Override
    public Integer checkData(String typeCode, String code, String id) {
        return sysdataMapper.checkData(typeCode,code,id);
    }

    /**
     * 保存数据到Redis
     * @return
     */
    @Override
    public boolean DataToRedis(){
        //查询表中所有数据
        List<HashMap<String, String>> list = sysdataMapper.querySysData(null);
        //批量操作
        Boolean delete = stringRedisTemplate.delete("data:sys_data");
        log.info("删除data:sys_data  ->  {}",delete);
        List<Object> objects = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.openPipeline();
                list.forEach( data ->{
                    //获取到一行的主键id，改id作为key的一部分
                    String id = data.get("id");
                    //存储在Redis中的key格式
                    String key = "data:sys_data:"+id;
                    //将行数据存入Redis
                    String value = JSONObject.toJSONString(data);
                    Boolean delete1 = stringRedisTemplate.delete("data:sys_data:*");
                    Boolean aBoolean = connection.hSet("data:sys_data".getBytes(), id.getBytes(), value.getBytes());
                } );
                return null;
            }
        });

        //将id存入Redis，value格式
        List<SysDataTypeDto> typeCodeAndTypeName = findTypeCodeAndTypeName(null);
        for (int i = 0; i < typeCodeAndTypeName.size(); i++) {
            SysDataTypeDto sysDataTypeDto = typeCodeAndTypeName.get(i);
            String id = sysDataTypeDto.getId();
            String typeCode = sysDataTypeDto.getTypeCode();
            String typeName = sysDataTypeDto.getTypeName();
            String key1 = "sys_data:id:typeCode:"+typeCode;
            String key2 = "sys_data:id:typeName:"+typeName;
            stringRedisTemplate.boundValueOps(key1).set(id);
            //设置过期时间,一天
            Boolean key1TimeOut = stringRedisTemplate.expire(key1, 24 * 60 * 60, TimeUnit.SECONDS);
            stringRedisTemplate.boundValueOps(key2).set(id);
            //设置过期时间,一天
            Boolean key2TimeOut = stringRedisTemplate.expire(key2, 24 * 60 * 60, TimeUnit.SECONDS);
        }
        //将id存入Redis，Zset格式
        List<Object> datas = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                connection.openPipeline();
                list.forEach( data ->{
                    //获取到一行的主键id，改id作为key的一部分
                    String id = data.get("id");
                    //存储在Redis中的key格式
                    String keyTypeCode = "data:sys_data:typeCode:"+data.get("typeCode");
                    String keyTypeName = "data:sys_data:typeName:"+data.get("typeName");
                    String keyName = "data:sys_data:name:"+data.get("name");
                    String keyCode = "data:sys_data:code:"+data.get("code");
                    //将id存入Redis
                    Long add = stringRedisTemplate.boundSetOps(keyTypeCode).add(id);
                    //设置过期时间,一天
                    Boolean expire = stringRedisTemplate.expire(keyTypeCode, 24 * 60 * 60, TimeUnit.SECONDS);

                    Long add1 = stringRedisTemplate.boundSetOps(keyTypeName).add(id);
                    //设置过期时间,一天
                    Boolean expire1 = stringRedisTemplate.expire(keyTypeName, 24 * 60 * 60, TimeUnit.SECONDS);

                    Long add2 = stringRedisTemplate.boundSetOps(keyName).add(id);
                    //设置过期时间,一天
                    Boolean expire2 = stringRedisTemplate.expire(keyName, 24 * 60 * 60, TimeUnit.SECONDS);

                    Long add3 = stringRedisTemplate.boundSetOps(keyCode).add(id);
                    //设置过期时间,一天
                    Boolean expire3 = stringRedisTemplate.expire(keyCode, 24 * 60 * 60, TimeUnit.SECONDS);
                } );
                return null;
            }
        });

        return true;
    }


    /**
     * 从redis中删除key
     * @param key  模糊的key
     * @return
     */
    @Override
    public boolean delKeyRedis(String key){
        RedisUtils redisUtils= new RedisUtils(stringRedisTemplate);
        List<String> keys = redisUtils.keys(key);
        log.info("接收的值key:{}",key);
        log.info("size:{}",keys.size());
        Long delete = stringRedisTemplate.delete(keys);
        log.info("删除的数量：{}",delete);
        return false;
    }
}
